#include "InvoiceItem.h"
#include <assert.h>

using namespace ecocity;

uint InvoiceItem::s_counter = 0;

//---------------------------------------------------------------

InvoiceItem::InvoiceItem( Customer::TYPE customer_type,
                          const Product& product,
                          int cantidad,
                          float discount_rate )
    : m_unique_id( ++s_counter ),
      m_customer_type( customer_type ),
      m_product( product ),
      m_quantity( cantidad ),
      m_weight( 0 ),
      m_discount_rate( discount_rate )
{
    update_costs( );
}

//---------------------------------------------------------------

void
InvoiceItem::set_quantity( int quantity )
{
    m_quantity = quantity;

    update_costs( );
}

//---------------------------------------------------------------

void
InvoiceItem::set_discount( float discount )
{
    m_discount = discount;

    update_costs( );
}

//---------------------------------------------------------------

void
InvoiceItem::set_product( const Product &product )
{
    m_product = product;

    update_costs( );
}

//---------------------------------------------------------------

void
InvoiceItem::set_weight( float kilograms )
{
    m_weight = kilograms;
    update_costs( );
}

//---------------------------------------------------------------

uint
InvoiceItem::id( ) const
{
    return m_unique_id;
}

//---------------------------------------------------------------

Customer::TYPE
InvoiceItem::customer_type( ) const
{
    return m_customer_type;
}

//---------------------------------------------------------------

Product::PRICE_TYPE
InvoiceItem::price_type( ) const
{
    return m_product.price_type( );
}

//---------------------------------------------------------------

const Product&
InvoiceItem::product( ) const
{
    return m_product;
}

//---------------------------------------------------------------

float
InvoiceItem::total_cost( ) const
{
    return m_total_cost;
}

//---------------------------------------------------------------

float
InvoiceItem::taxes_cost( ) const
{
    return m_total_taxes;
}

//---------------------------------------------------------------

int
InvoiceItem::tax_rate( ) const
{
    return m_product.tax_rate( );
}

//---------------------------------------------------------------

float
InvoiceItem::untaxed_cost_with_discount( ) const
{
    return m_cost_without_taxes;
}

//---------------------------------------------------------------

float
InvoiceItem::untaxed_cost_without_discount( ) const
{
    return m_cost_without_taxes_without_discount;
}

//---------------------------------------------------------------

int
InvoiceItem::quantity( ) const
{
    return m_quantity;
}

//---------------------------------------------------------------

float
InvoiceItem::weight( ) const
{
    return m_weight;
}

//---------------------------------------------------------------

float
InvoiceItem::discount_rate( ) const
{
    return m_discount_rate;
}

//---------------------------------------------------------------

float
InvoiceItem::total_discount( ) const
{
    return m_discount;
}

//---------------------------------------------------------------

float
InvoiceItem::profit( ) const
{
    return m_total_profit;
}

//---------------------------------------------------------------

void
InvoiceItem::update_costs( )
{
    float untaxed_ecocity_cost = 0;

    switch ( m_product.price_type( ) )
    {
    case Product::PER_KILO:
    {
        untaxed_ecocity_cost = m_quantity * m_weight * m_product.raw_price( );
        m_discount = m_quantity * m_weight * m_product.untaxed_price( m_customer_type ) * m_discount_rate / 100;
        m_cost_without_taxes_without_discount = ( m_quantity * m_weight * m_product.untaxed_price( m_customer_type ) );
        break;
    }
    case Product::PER_UNIT:
    {
        untaxed_ecocity_cost = m_quantity * m_product.raw_price( );
        m_discount = m_quantity * m_product.untaxed_price( m_customer_type ) * m_discount_rate / 100;
        m_cost_without_taxes_without_discount = ( m_quantity * m_product.untaxed_price( m_customer_type ) );
        break;
    }
    default:
    {
        assert( 0 );
        break;
    }

    }

    float taxed_ecocity_cost = untaxed_ecocity_cost + ( untaxed_ecocity_cost * m_product.tax_rate( ) / 100 );

    m_cost_without_taxes = m_cost_without_taxes_without_discount - m_discount;
    m_total_taxes = m_cost_without_taxes * m_product.tax_rate( ) / 100;
    m_total_cost = m_cost_without_taxes + m_total_taxes; // includes discount
    m_total_profit = m_total_cost - taxed_ecocity_cost; // includes discount

}
